package com.box.annotation;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.box.entity.DbAdmin;
import com.box.entity.DbLog;
import com.box.service.LogService;
import com.box.utils.MyUtil;
import com.box.utils.WebUtils;
import com.box.utils.wx.DateUtil;



/**   
*    
* 项目名称：MyBox   
* 类名称：SystemLogAspect   
* 类描述：   切点类
* 创建人：君无邪   
* 创建时间：2019年10月16日 下午12:15:23   
* 修改人：君无邪 
* 修改时间：2019年10月16日 下午12:15:23   
* 修改备注：  https://www.java214.com 
* @version    
*    
*/ 
@Aspect    
@Component 
public class SystemLogAspect {
	
	@Autowired
	private LogService logService;
	
	  //本地异常日志记录对象    
    private  static  final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);    

    @Pointcut("@annotation(com.box.annotion.SysLog)")    
    public  void controllerAspect() {    
    	System.out.println("=====可以打印日志啦");
   } 
    
    /**  
     * 前置通知 用于拦截Controller层记录用户的操作  
     *  
     * @param joinPoint 切点  
     */    
    @Before("controllerAspect()")    
     public  void doBefore(JoinPoint joinPoint) {    
    	ServletRequestAttributes ras = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ras.getRequest();
        HttpSession session = request.getSession();    
        //读取session中的用户    
        DbAdmin user = (DbAdmin)SecurityUtils.getSubject().getPrincipal();   
        //请求的IP    
        //String ip = request.getRemoteAddr();
        
        String requestURI=request.getRequestURI();
        
        String ip=WebUtils.getRemoteAddr(request);
        String method = joinPoint.getSignature().getDeclaringTypeName() + 
                "." + joinPoint.getSignature().getName();
        String params = ""; 
        if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {    
            for ( int i = 0; i < joinPoint.getArgs().length; i++) {    
           	 params+=joinPoint.getArgs()[i]+";";   
           }    
       }    
         try {    
            //*========控制台输出=========*//    
           System.out.println("=====前置通知开始=====");    
            String operation=getControllerMethodDescription(joinPoint);    
            String username=user.getUsername();
           System.out.println("请求参数:" + params);    
    
            DbLog log=new DbLog();
            String nowDateStr2 = MyUtil.getNowDateStr2();
            log.setCreateTime(DateUtil.str2Date(nowDateStr2, "yyyy-MM-dd HH:mm:ss"));
            log.setIp(ip);
            log.setOperation(operation);
            log.setParams(params);
            log.setUsername(username);
            log.setMethod(requestURI);
			//*========保存数据库日志=========*// 
           System.out.println(log);
            logService.insertLof(log);
            logger.info(username+".......log日志");
            logger.info(method+".........log日志扫描方法");
            //保存数据库    
        }  catch (Exception e) {    
            //记录本地异常日志    
            logger.error("==前置通知异常==");    
            logger.error("异常信息:{}", e.getMessage());    
        }    
    }    
    
    /**  
     * 获取注解中对方法的描述信息 用于Controller层注解  
     *  
     * @param joinPoint 切点  
     * @return 方法描述  
     * @throws Exception  
     */    
     public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {    
        String targetName = joinPoint.getTarget().getClass().getName();    
        String methodName = joinPoint.getSignature().getName();    
        Object[] arguments = joinPoint.getArgs();    
        Class<?> targetClass = Class.forName(targetName);    
        Method[] methods = targetClass.getMethods();    
        String description = "";    
         for (Method method : methods) {    
             if (method.getName().equals(methodName)) {    
                @SuppressWarnings("rawtypes")
				Class[] clazzs = method.getParameterTypes();    
                 if (clazzs.length == arguments.length) {    
                    description = method.getAnnotation(SysLog. class).value();    
                     break;    
                }    
            }    
        }    
         return description;    
    }    
}
